<?php
namespace Hilaoyu\LaravelExtend\Traits;

use Hilaoyu\Utils\UtilSupport;
use Illuminate\Support\Facades\Validator as ValidatorFactory;
use Hilaoyu\LaravelExtend\Supports\Uuid;

trait ModelCommonTrait
{
    protected $table_columns = [];
    protected $_accessIdentifier = null;

    public function __construct()
    {
        try{
            $args = func_get_args();
            parent::__construct(...$args);
        }catch (\Exception $e){

        }

        $this->eventOnConstruct();
        $this->_fireTraitEvents('eventOnConstruct',false);
    }

    static public function makeModel($id='',$new_if_not_exists=false){
        $model = new static();

        if(!empty($id)){

            if($id instanceof static){
                $model = $id;
            }else{
                if(is_string($id)){
                    $model = $model->find($id);
                }else{
                    $model = $model->where($id)->first();
                }

                if(! $model && $new_if_not_exists){
                    $model = $model = new static();
                    $model->{$model->getKeyName()} = $id;
                }
            }

        }


        return $model;
    }


    /**
     * 验证规则
     *
     * */
    public function getValidationRules()
    {
        return [];
    }
    public function getValidationMessages()
    {
        return [];
    }


    /**
     * 验证
     * @param null $data 要验证的数据
     * @param null $rules 验证规则
     * @return bool
     */
    public function validate($data = null, $rules = null)
    {
        if (is_null($data)) {
            $data = $this->getAttributes();
        }

        if (is_null($rules)) {
            $rules = $this->getValidationRules();
        }

        if ($this->primaryKeyIsUuid() ) {
            $rules[$this->getKeyName()] = 'required|uuid';
        }


        if ($this->exists) {
            foreach ($rules as $field => $rule) {
                if (!array_key_exists($field,$data)) {
                    unset($rules[$field]);
                }
            }
        }

        $V = ValidatorFactory::make($data, $rules,$this->getValidationMessages());
        if ($V->fails()) {
            $messages = $V->errors()->messages();
            UtilSupport::tryQuiet(function () use ($messages){
                $this->setError($messages);
            });


            return false;
        }

        return true;
    }

    /**
     * 数据表字段
     * @return array
     */
    public function getTableColumns()
    {
        if (empty($this->table_columns)) {
            $this->table_columns = $this->getConnection()->getSchemaBuilder()->getColumnListing($this->getTable());
        }
        return $this->table_columns;
    }

    /**
     * 数据表中是否有某字段
     * @param $column
     * @return bool
     */
    public function tableHasColumn($column)
    {
        $column = trim($column);
        if (empty($column)) {
            return false;
        }
        $columns = $this->getTableColumns();
        return in_array($column, $columns);
    }


    /**
     * 返回表名，包含链接名
     * */
    static public function getTableCon()
    {
        return UtilSupport::makeClassSingle(static::class)->getConnectionName() . '.' . static::getTableName();
    }

    /**
     * 静态方法 返回表名
     * @return mixed
     */
    static public function getTableName()
    {
        return UtilSupport::makeClassSingle(static::class)->getTable();
    }

    /**
     * 静态方法 返回主键名
     * */
    static public function getPkName()
    {
        return UtilSupport::makeClassSingle(static::class)->getKeyName();

    }

    /**
     * 静态方法 返回主键类型
     * */
    static public function getPkType()
    {
        return UtilSupport::makeClassSingle(static::class)->getKeyType();

    }


    /**
     * 主建类型是否为uuid
     * @return bool
     */
    public function primaryKeyIsUuid()
    {
        return $this->getKeyName() && $this->getKeyType() == 'uuid';
    }

    public function getOriginalKey(){
        return $this->getOriginal($this->getKeyName());
    }

    public function fillPrimaryKeyUuid($force=false){
        if($force){
            $this->{$this->getKeyName()} = (string)Uuid::generate();
        }else{
            $key = $this->getKey();
            if(!$key || !Uuid::verify($key)){
                $this->{$this->getKeyName()} = (string)Uuid::generate();
            }
        }
        return $this;
    }

    //events

    public function eventOnConstruct(){

    }

    public function eventOnRetrieved(){
        return $this->_fireTraitEvents('eventOnRetrieved',false);
    }

    /**
     * 新加时自动生成uuid
     * @return bool
     */
    public function eventOnCreating(){
        if ($this->primaryKeyIsUuid() ) {
            $this->fillPrimaryKeyUuid();
        }

        return $this->_fireTraitEvents('eventOnCreating',true);
    }
    /**
     * 新加时自动生成uuid
     * @return bool
     */
    public function eventOnCreated(){
        return $this->_fireTraitEvents('eventOnCreated',false);
    }

    /**
     * 更新时不能修改uuid
     * @return bool
     */
    public function eventOnUpdating(){
        /*if ($this->primaryKeyIsUuid()) {
            $original_uuid = $this->getOriginalKey();

            if ($original_uuid !== $this->getKey()) {
                $this->{$this->getKeyName()} = $original_uuid;
            }
        }*/
        return $this->_fireTraitEvents('eventOnUpdating',true);
    }

    public function eventOnUpdated(){
        return $this->_fireTraitEvents('eventOnUpdated',false);
    }



    /**
     * 保存前验证数据合法性
     * @return bool
     */
    public function eventOnSaving(){
        if ($this->primaryKeyIsUuid() ) {
            $this->fillPrimaryKeyUuid();
        }
        if(!$this->validate()){
            return false;
        }

        return $this->_fireTraitEvents('eventOnSaving',true);
    }

    public function eventOnSaved(){
        return $this->_fireTraitEvents('eventOnSaved',false);
    }

    public function eventOnDeleting(){
        return $this->_fireTraitEvents('eventOnDeleting',true);
    }


    public function eventOnDeleted(){
        return $this->_fireTraitEvents('eventOnDeleted',false);
    }

    public function eventOnRestoring(){
        return $this->_fireTraitEvents('eventOnRestoring',true);
    }


    public function eventOnRestored(){
        return $this->_fireTraitEvents('eventOnRestored',false);
    }

    protected function _fireTraitEvents($event,$break=false){
        $trait_event_executed = [];
        $flag = true;
        foreach (class_uses_recursive($this) as $trait) {

            $method = $event . class_basename($trait);

            if (method_exists($this, $method) && ! in_array($method, $trait_event_executed)) {
                $flag = $this->{$method}();
                if($break && !$flag){
                    break;
                }

                $trait_event_executed[] = $method;
            }
        }

        return $flag;
    }

    /**
     * 注册监听事件
     */
    protected static function boot()
    {

        //从数据库中获取已存在模型时触发
        static::retrieved(function ($model) {
            //自动生成uuid

            if(method_exists($model,'eventOnRetrieved')){
                $model->eventOnRetrieved();
            }

        });

        //新加时入库前
        static::creating(function ($model) {

            if(method_exists($model,'eventOnCreating')){
                return $model->eventOnCreating();
            }
            return true;
        });

        //新增完成,基础版本
        static::created(function ($model){

            if(method_exists($model,'eventOnCreated')){
                $model->eventOnCreated();
            }
        });

        //更新时入库前
        static::updating(function ($model) {
            if(method_exists($model,'eventOnUpdating')){
                return $model->eventOnUpdating();
            }
            return true;
        });

        //更新完成时
        static::updated(function ($model) {
            if(method_exists($model,'eventOnUpdated')){
                $model->eventOnUpdated();
            }

        });

        //保存前
        static::saving(function ($model) {
            if(method_exists($model,'eventOnSaving')){
                return $model->eventOnSaving();
            }

            return true;
        });


        //保存后
        static::saved(function ($model) {

            if(method_exists($model,'eventOnSaved')){
                $model->eventOnSaved();
            }
        });

        //删除前
        static::deleting(function ($model) {
            $flag = true;
            if(method_exists($model,'eventOnDeleting')){
                UtilSupport::tryQuiet(function () use ($model,&$flag){
                    $model->getConnection()->transaction(function ($connection) use ($model,&$flag){
                        $flag = $model->eventOnDeleting();
                        if(!$flag){

                            throw new \Exception('');
                        }
                    });
                });


            }
            return $flag;
        });
        //删除后
        static::deleted(function ($model) {
            if(method_exists($model,'eventOnDeleted')){
                $model->eventOnDeleted();
            }
        });

        try{
            //软删除恢复前
            static::restoring(function ($model) {

                if(method_exists($model,'eventOnRestoring')){
                    $model->eventOnRestoring();
                }
            });
            //软删除恢复后
            static::restored(function ($model) {

                if(method_exists($model,'eventOnRestored')){
                    $model->eventOnRestored();
                }
            });
        }catch (\Exception $e){

        }


        parent::boot();
    }
}
